<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Str;

class NewTFileCommand extends Command
{
    /**
     * 指令
     * @var string
     */
    protected $signature = 'make:tfile {template : 模版名称(将创建 controller、service、model) 多层用 /或. 隔开，如：admin/user}';

    /**
     * 指令描述
     * @var string
     */
    protected $description = '创建 模板文件 (包括 controller service model)';

    protected array $className = [
        'Controller',
        'Service',
        'Model',
    ];

    protected array $namespace = [
        'App\Http\Controllers',
        'App\Services',
        'App\Models',
    ];

    protected array $templateFile = [
        'controller.stub',
        'service.stub',
        'model.stub',
    ];

    protected array $searchTemplate = [
        '{$namespace}',     // 当前 命名空间
        '{$class}',         // 当前 类

        // $namespace
        '{$controllerNamespace}',   // cn
        '{$serviceNamespace}',      // sn
        '{$modelNamespace}',        // mn

        // $className
        '{$controller}',    // c
        '{$service}',       // s
        '{$model}',         // m

        '{$table}'
    ];

    /**
     * 指令执行内容
     */
    public function handle(): void
    {
        $template = $this->argument('template');
        // 切分模块  admin/user  转换  ['Admin', 'User']
        $separators = ['.', '/'];
        $params = [];
        foreach ($separators as $separator) {
            if (str_contains($template, $separator)) {
                $params = array_map(fn($v) => ucwords($v), explode($separator, $template));
                break;
            }
        }
        if (!$params) $params = [ucwords($template)];
        $routeUrl = str_replace('_', '/', Str::snake(implode('/',$params)));
        $routeController = implode('\\',$params). 'Controller';
        $class = Str::studly(array_pop($params));
        foreach ($params as $module) {
            $this->namespace = array_map(fn($v) => $v . '\\' . $module, $this->namespace);
        }
        $classN = array_map(fn($v) => $class . $v, $this->className);
        $classNs = array_map(fn($a, $b) => $a . '\\' . $b, $this->namespace, $classN);

        foreach ($this->namespace as $k => $ns) {
            if (!is_dir($path = $this->ns2path($ns)) && !mkdir($path, 0755)) {
                $this->error('无法创建 目录:' . $path);
            }
            $tFile = $path . '/' . $classN[$k] . '.php';
            if (is_file($tFile)) continue;
            $content = file_get_contents(__DIR__ . '/templates/' . $this->templateFile[$k]);
            file_put_contents($tFile, str_replace(
                $this->searchTemplate,
                [$ns, $classN[$k], ...$classNs, ...$classN, Str::snake($class)],
                $content));
        }
        // 处理路由、
        if (is_file(base_path('routes/web.php'))) {
            $content = file_get_contents(__DIR__. '/templates/route.stub');
            file_put_contents(base_path('routes/web.php'), str_replace(['{$url}', '{$controller}'], [$routeUrl, $routeController], $content), FILE_APPEND);
        }
        $this->info('完成！！');
    }

    /**
     * namespace 转换为路径
     * @param string $namespace
     * @return string
     */
    protected function ns2path(string $namespace): string
    {
        $psr4 = json_decode(file_get_contents(base_path('composer.json')), true)['autoload']['psr-4'] ?? [];
        $res = str_replace([...array_keys($psr4), '\\'], [...array_values($psr4), '/'], $namespace);
        return base_path($res);
    }
}
